<template>
  <div class="home" ref="screen">
    <div class="top">
      <div class="top-left">
        <img src="/src/assets/images/icon.png" alt="" />
        可交互ROS消息动画
      </div>
    </div>
    <div class="main">
      <div class="message">
        <div class="msg-left">
          <p class="text-gray-600 font-semibold mb-2" style="font-size: 16px">
            点击任意A、B话题输入传输信息
          </p>
          <p class="msg-text">
            <SvgIcon name="edit" size="24" />
            发布端
          </p>
        </div>
        <div>
          <p class="text-gray-600 font-semibold mb-2 opacity-0">
            点击任意A、B话题输入传输信息
          </p>
          <div class="msg-right">
            <SvgIcon name="flag" size="28" />
            订阅端
          </div>
        </div>
      </div>
      <el-row class="mt-8 w-full relative">
        <div class="text n1" v-if="letterShow.includes(1)">✉</div>
        <div class="text n2" v-if="letterShow.includes(2)">✉</div>
        <div class="text n3" v-if="letterShow.includes(3)">✉</div>
        <div class="text n4" v-if="letterShow.includes(4)">✉</div>
        <div class="text n5" v-if="letterShow.includes(5)">✉</div>
        <div class="text n6" v-if="letterShow.includes(6)">✉</div>
        <div class="text n7" v-if="letterShow.includes(7)">✉</div>
        <div class="text n8" v-if="letterShow.includes(8)">✉</div>
        <el-col :span="8">
          <div class="send-content">
            <div class="node-content">
              <div
                class="node"
                ref="node1Ref"
                v-if="nodeSendCount === 1 || nodeSendCount === 2"
                @click="handleSend(1)"
              >
                <p>Node1</p>
                <div class="publisher">publisher</div>
              </div>
              <div
                class="node"
                ref="node2Ref"
                v-if="nodeSendCount === 2"
                @click="handleSend(2)"
              >
                <p>Node2</p>
                <div class="publisher">publisher</div>
              </div>
            </div>
          </div>
        </el-col>
        <el-col :span="8">
          <div class="centre">
            <div
              class="topic topic-left"
              ref="topicARef"
              :style="'opacity:' + (topicShow === 1 || topicShow === 3 ? 1 : 0)"
            >
              topicA
            </div>
            <div
              class="topic topic-right"
              ref="topicBRef"
              :style="'opacity:' + (topicShow === 2 || topicShow === 3 ? 1 : 0)"
            >
              topicB
            </div>
          </div>
        </el-col>
        <el-col :span="8">
          <div class="subscription">
            <div class="send-content">
              <div class="node-content node-right">
                <div
                  class="node n-right"
                  ref="node3Ref"
                  v-if="nodeSubCount === 1 || nodeSubCount === 2"
                >
                  <div class="subscriber">subscriber</div>
                  <p>Node3</p>
                  <p class="getMessage">
                    接收消息:{{
                      [...new Set(node3Text.split('\u00A0'))].join('\u00A0')
                    }}
                  </p>
                </div>
                <div
                  class="node n-right"
                  ref="node4Ref"
                  v-if="nodeSubCount === 2"
                >
                  <div class="subscriber">subscriber</div>
                  <p>Node4</p>
                  <p class="getMessage">
                    接收消息:{{
                      [...new Set(node4Text.split('\u00A0'))].join('\u00A0')
                    }}
                  </p>
                </div>
              </div>
            </div>
          </div>
        </el-col>
      </el-row>
      <div class="btns">
        <div class="btn btn-1" @click="handleOpen">
          <SvgIcon name="add" size="20" />
          新增
        </div>
        <div class="btn btn-2" @click="handleRefresh">
          <SvgIcon name="again" size="20" />
          复位
        </div>
      </div>
    </div>

    <Dialog ref="dialogRef" @addTopic="handleAddTopic" :topicShow="topicShow" />
    <Send ref="sendRef" @sendMsg="handleSendMsg" />
  </div>
</template>

<script setup lang="ts">
import LeaderLine from 'leader-line-vue'
import Send from './components/send.vue'

const dialogRef = ref()
const sendRef = ref()
const node1Ref = ref()
const node2Ref = ref()
const node3Ref = ref()
const node4Ref = ref()
const topicARef = ref()
const topicBRef = ref()

// 发布端node数量
const nodeSendCount = ref(0)
// topic显示
const topicShow = ref(0)
// 订阅端node数量
const nodeSubCount = ref(0)
// 线条
const line = ref<any>([])
// node关联记录
const nodeHistory = ref<any>([])
// 话题A消息记录
const topicAText = ref('')
// 话题B消息记录
const topicBText = ref('')
const node3Text = ref('')
const node4Text = ref('')

// 动画展示
const letterShow = ref<any>([])

// 弹窗
const handleOpen = () => {
  dialogRef.value.showFn()
}

// 发布端点击
const handleSend = (status: number) => {
  sendRef.value.showFn(status)
}

// 复位
const handleRefresh = () => {
  // 删除所有线条
  line.value.forEach((l: any) => l.remove())
  line.value = [] // 清空线条数组
  nodeSendCount.value = 0
  nodeSubCount.value = 0
  topicShow.value = 0
  letterShow.value = []
  nodeHistory.value = []
  topicAText.value = ''
  topicBText.value = ''
  node3Text.value = ''
  node4Text.value = ''
}

// 连线
const getLine = (
  from: any,
  to: any,
  // text?: string,
  isAnimation?: boolean,
) => {
  // 查找是否已经存在该连接的线
  const existingLineIndex = line.value.findIndex(
    (l: any) => l.start === from && l.end === to,
  )
  const options: any = {
    color: '#6769fb', // 线条颜色（蓝色）
    size: 1,
    endPlugSize: 3,
    endPlugOutlineSize: 3,
    startSocket: 'right',
    endSocket: 'left',
    path: 'straight',
  }

  // if (text) {
  //   isTop
  //     ? (options.startLabel = `✉${text}`)
  //     : (options.endLabel = `✉${text}`)
  // }

  if (isAnimation) {
    options.dash = { animation: true } // 动画效果
  } else {
    options.dash = { len: 6, gap: 6 }
  }

  if (existingLineIndex !== -1) {
    // 如果已经存在该线条，先删除
    line.value[existingLineIndex].remove()
    // 创建新线条并替换到原位置
    const newLine = LeaderLine.setLine(from, to, options)
    line.value.splice(existingLineIndex, 1, newLine) // 替换数组中的元素
  } else {
    // 如果没有现有线条，创建新线条并添加到数组
    const newLine = LeaderLine.setLine(from, to, options)
    line.value.push(newLine)
  }
}

// 新增确认
const handleAddTopic = (active: number, data: any) => {
  // 发布接收显示
  if (active === 1) {
    if (nodeSendCount.value < 2) {
      nodeSendCount.value++
    } else {
      ElMessage.error('最多添加两个发布端节点')
      return
    }
  } else if (active === 2) {
    if (nodeSubCount.value < 2) {
      nodeSubCount.value++
    } else {
      ElMessage.error('最多添加两个订阅端节点')
      return
    }
  }

  // topic显示并连线
  if (data.checked1 && data.checked2) {
    topicShow.value = 3
    if (active === 1) {
      // 对应node连接topicA和B
      // 展示的是node1
      if (nodeSendCount.value === 1) {
        nextTick(() => {
          getLine(node1Ref.value, topicARef.value)
          getLine(node1Ref.value, topicBRef.value)
          // 记录连线
          nodeHistory.value.push({ who: 1, line: 3 }) // 1代表node1，3代表A和B都连
        })
      }
      // 展示的是node2
      if (nodeSendCount.value === 2) {
        nextTick(() => {
          getLine(node2Ref.value, topicARef.value)
          getLine(node2Ref.value, topicBRef.value)
          // 记录连线
          nodeHistory.value.push({ who: 2, line: 3 }) // 2代表node2，3代表A和B都连
        })
      }
    } else if (active === 2) {
      if (nodeSubCount.value === 1) {
        nextTick(() => {
          getLine(topicARef.value, node3Ref.value)
          getLine(topicBRef.value, node3Ref.value)
          // 记录连线
          nodeHistory.value.push({ who: 3, line: 3 }) // 3代表node3，3代表A和B都连
        })
      }
      if (nodeSubCount.value === 2) {
        nextTick(() => {
          getLine(topicARef.value, node4Ref.value)
          getLine(topicBRef.value, node4Ref.value)
          // 记录连线
          nodeHistory.value.push({ who: 4, line: 3 }) // 4代表node4，3代表A和B都连
        })
      }
    }
  } else if (data.checked1) {
    if (topicShow.value && topicShow.value !== 1) {
      topicShow.value = 3
    } else {
      topicShow.value = 1
    }
    if (active === 1) {
      // 对应node连接topicA
      // 展示的是node1
      if (nodeSendCount.value === 1) {
        nextTick(() => {
          getLine(node1Ref.value, topicARef.value)
          // 记录连线
          nodeHistory.value.push({ who: 1, line: 1 }) // 1代表node1，1代表A
        })
      }
      // 展示的是node2
      if (nodeSendCount.value === 2) {
        nextTick(() => {
          getLine(node2Ref.value, topicARef.value)
          // 记录连线
          nodeHistory.value.push({ who: 2, line: 1 }) // 2代表node2，1代表A
        })
      }
    } else if (active === 2) {
      if (nodeSubCount.value === 1) {
        nextTick(() => {
          getLine(topicARef.value, node3Ref.value)
          // 记录连线
          nodeHistory.value.push({ who: 3, line: 1 }) // 3代表node3，1代表A
        })
      }
      if (nodeSubCount.value === 2) {
        nextTick(() => {
          getLine(topicARef.value, node4Ref.value)
          // 记录连线
          nodeHistory.value.push({ who: 4, line: 1 }) // 4代表node4，1代表A
        })
      }
    }
  } else if (data.checked2) {
    if (topicShow.value && topicShow.value !== 2) {
      topicShow.value = 3
    } else {
      topicShow.value = 2
    }
    if (active === 1) {
      // 对应node连接topicB
      // 展示的是node1
      if (nodeSendCount.value === 1) {
        nextTick(() => {
          getLine(node1Ref.value, topicBRef.value)
          // 记录连线
          nodeHistory.value.push({ who: 1, line: 2 }) // 1代表node1，2代表B
        })
      }
      // 展示的是node2
      if (nodeSendCount.value === 2) {
        nextTick(() => {
          getLine(node2Ref.value, topicBRef.value)
          // 记录连线
          nodeHistory.value.push({ who: 2, line: 2 }) // 2代表node2，2代表B
        })
      }
    } else if (active === 2) {
      if (nodeSubCount.value === 1) {
        nextTick(() => {
          getLine(topicBRef.value, node3Ref.value)
          // 记录连线
          nodeHistory.value.push({ who: 3, line: 2 }) // 3代表node3，2代表B
        })
      }
      if (nodeSubCount.value === 2) {
        nextTick(() => {
          getLine(topicBRef.value, node4Ref.value)
          // 记录连线
          nodeHistory.value.push({ who: 4, line: 2 }) // 4代表node4，2代表B
        })
      }
    }
  }

  nextTick(() => {
    nodeHistory.value.forEach((record: { who: number; line: number }) => {
      // 订阅者记录
      if (record.who === 3) {
        // 判断订阅者对应的连线
        if (record.line === 1) {
          if (topicAText.value) {
            letterShow.value.push(5)
            node3Text.value += topicAText.value
          }
        } else if (record.line === 2) {
          if (topicBText.value) {
            letterShow.value.push(7)
            node3Text.value += topicBText.value
          }
        } else if (record.line === 3) {
          if (topicAText.value && topicBText.value) {
            letterShow.value.push(5, 7)
            node3Text.value += topicAText.value += topicBText.value
          } else if (topicAText.value) {
            letterShow.value.push(5)
            node3Text.value += topicAText.value
          } else if (topicBText.value) {
            letterShow.value.push(7)
            node3Text.value += topicBText.value
          }
        }
      } else if (record.who === 4) {
        // 判断订阅者对应的连线
        if (record.line === 1) {
          if (topicAText.value) {
            letterShow.value.push(6)
            node4Text.value += topicAText.value
          }
        } else if (record.line === 2) {
          if (topicBText.value) {
            letterShow.value.push(8)
            node4Text.value += topicBText.value
          }
        } else if (record.line === 3) {
          if (topicAText.value && topicBText.value) {
            letterShow.value.push(6, 8)
            node4Text.value += topicAText.value += topicBText.value
          } else if (topicAText.value) {
            letterShow.value.push(6)
            node4Text.value += topicAText.value
          } else if (topicBText.value) {
            letterShow.value.push(8)
            node4Text.value += topicBText.value
          }
        }
      }
    })
  })
}

// 发送确认
const handleSendMsg = (text: string, who: number) => {
  // 遍历nodeHistory，找到对应的节点，然后获取对应的topic
  nodeHistory.value.forEach((record: { who: number; line: number }) => {
    // 发布者记录
    if (record.who === who) {
      if (record.line === 1 || record.line === 3) {
        who === 1 ? letterShow.value.push(1) : letterShow.value.push(3)
      }
      if (record.line === 2 || record.line === 3) {
        who === 1 ? letterShow.value.push(2) : letterShow.value.push(4)
      }
      if (record.line === 1) {
        topicAText.value += text + '\u00A0'
      } else if (record.line === 2) {
        topicBText.value = text + '\u00A0'
      } else if (record.line === 3) {
        topicAText.value += text + '\u00A0'
        topicBText.value += text + '\u00A0'
      }
    }

    nextTick(() => {
      // 订阅者记录
      if (record.who === 3) {
        // 判断订阅者对应的连线
        if (record.line === 1) {
          if (topicAText.value) {
            letterShow.value.push(5)
            node3Text.value += topicAText.value
          }
        } else if (record.line === 2) {
          if (topicBText.value) {
            letterShow.value.push(7)
            node3Text.value += topicBText.value
          }
        } else if (record.line === 3) {
          if (topicAText.value && topicBText.value) {
            letterShow.value.push(5, 7)
            node3Text.value += topicAText.value += topicBText.value
          } else if (topicAText.value) {
            letterShow.value.push(5)
            node3Text.value += topicAText.value
          } else if (topicBText.value) {
            letterShow.value.push(7)
            node3Text.value += topicBText.value
          }
        }
      } else if (record.who === 4) {
        // 判断订阅者对应的连线
        if (record.line === 1) {
          if (topicAText.value) {
            letterShow.value.push(6)
            node4Text.value += topicAText.value
          }
        } else if (record.line === 2) {
          if (topicBText.value) {
            letterShow.value.push(8)
            node4Text.value += topicBText.value
          }
        } else if (record.line === 3) {
          if (topicAText.value && topicBText.value) {
            letterShow.value.push(6, 8)
            node4Text.value += topicAText.value += topicBText.value
          } else if (topicAText.value) {
            letterShow.value.push(6)
            node4Text.value += topicAText.value
          } else if (topicBText.value) {
            letterShow.value.push(8)
            node4Text.value += topicBText.value
          }
        }
      }
    })
  })
}
</script>

<style lang="scss" scoped>
.home {
  .top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: url(/src/assets/images/top-bg.jpg) no-repeat center;
    background-size: cover;
    padding-left: 3vw;
    height: 10vh;

    .top-left {
      font-size: 24px;
      color: #3880e4;
      font-weight: 600;
      display: flex;
      align-items: center;
      gap: 0.4vw;

      & > img {
        width: 42px;
        height: 32px;
      }
    }
  }

  .main {
    height: 90vh;
    display: flex;
    flex-direction: column;
    background: url(/src/assets/images/main-bg.jpg) no-repeat center;
    background-size: cover;

    .message {
      padding: 3vh 6vw;
      display: flex;
      justify-content: space-between;

      .msg-text {
        font-weight: 600;
        color: #3880e4;
        font-size: 18px;
        fill: #3880e4;
        display: flex;
        gap: 8px;
        align-items: center;
      }

      .msg-right {
        color: #2fb5b6;
        font-size: 18px;
        display: flex;
        gap: 8px;
        align-items: center;
        justify-content: end;
        fill: #2fb5b6;
        font-weight: 600;
      }
    }
  }
}

.btns {
  display: flex;
  justify-content: center;
  margin-top: 5vh;

  .btn {
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 120px;
    height: 40px;
    border-radius: 40px;
    color: #fff;
    fill: #fff;
    font-size: 20px;
    gap: 4px;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
  }
  .btn-1 {
    background-color: #1faefc;
  }
  .btn-2 {
    margin-left: 32px;
    background-color: #f56830;
  }
}

.centre {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20vh;

  .topic {
    width: 12vw;
    height: 5vw;
    border-radius: 3vw;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    color: #fff;
    background-color: #a97aff;
  }
}

.send-content {
  width: 100%;
  height: 50vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10%;

  .node-content {
    width: 80%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    padding: 4vh 0;
    background-color: #f5f6fa;
    border-radius: 12px;
    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
  }

  .node {
    cursor: pointer;
    width: 80%;
    height: 40%;
    border-radius: 20px;
    background-color: #3882e5;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;

    p {
      font-size: 20px;
      font-weight: 600;
      color: #fff;
    }

    .publisher {
      width: 70%;
      height: 28%;
      border-radius: 100vh;
      background-color: #d7ecfd;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 14px;
      gap: 16px;
    }

    .subscriber {
      width: 70%;
      height: 28%;
      border-radius: 100vh;
      background-color: #b6e2e5;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 14px;
    }
  }

  .node-right {
    background-color: #eaf9fc;
  }

  .n-right {
    background-color: #2fb5b6;
  }
}

.getMessage {
  font-size: 12px !important;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
}

.text {
  z-index: 1;
  position: absolute;
  font-size: 16px;
  color: #67c23a;
}

@for $i from 1 through 8 {
  .n#{$i} {
    animation: flowText#{$i} 3s linear infinite;
  }
}

@keyframes flowText1 {
  0% {
    top: 18%;
    left: 25%;
  }
  100% {
    top: 18%;
    left: 42%;
  }
}

@keyframes flowText2 {
  0% {
    top: 18%;
    left: 25%;
  }
  100% {
    top: 62%;
    left: 42%;
  }
}

@keyframes flowText3 {
  0% {
    top: 66%;
    left: 25%;
  }
  100% {
    top: 18%;
    left: 42%;
  }
}

@keyframes flowText4 {
  0% {
    top: 68%;
    left: 25%;
  }
  100% {
    top: 68%;
    left: 42%;
  }
}

@keyframes flowText5 {
  0% {
    top: 18%;
    left: 55%;
  }
  100% {
    top: 18%;
    left: 72%;
  }
}

@keyframes flowText6 {
  0% {
    top: 18%;
    left: 55%;
  }
  100% {
    top: 64%;
    left: 72%;
  }
}

@keyframes flowText7 {
  0% {
    top: 66%;
    left: 55%;
  }
  100% {
    top: 18%;
    left: 74%;
  }
}

@keyframes flowText8 {
  0% {
    top: 68%;
    left: 55%;
  }
  100% {
    top: 68%;
    left: 76%;
  }
}
</style>
